
import 'package:fast_contacts/fast_contacts.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:lpinyin/lpinyin.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:share_fit/app/controllers/base/base_controller.dart';
import 'package:share_fit/app/helper/ext/tr_ext.dart';
import 'package:share_fit/app/models/device/contact_model.dart';
import 'package:share_fit/app/tools/log_utils.dart';
import 'package:share_fit/app/ute/uteped_const.dart';
import 'package:share_fit/generated/locales.g.dart';

import 'import_contacts_state.dart';

class ImportContactsLogic extends BaseController {

  static const contactsSynced = "contactsListSynced";
  static const methodSyncContactsInfoToDevice = "syncContactsInfoToDevice";

  final ImportContactsState state = ImportContactsState();

  Future<void> _fetchContacts() async {
    showLoading();
    state.contactList.clear();
    List<ContactModel> contactList = <ContactModel>[];
    Map<String, ContactModel> contactMap = {};
    List<ContactField> fields = ContactField.values.toList();
    try {
      List<Contact> contacts = await FastContacts.getAllContacts(fields: fields);

      state.totalCount = 0;
      for (var contact in contacts) {
        if (contact.displayName.isEmpty) {
          continue;
        }

        var py = PinyinHelper.getShortPinyin(contact.displayName);
        if (py.isEmpty) {
          py = "#";
        }

        var initial = py.substring(0, 1).toUpperCase();
        ContactModel model;
        if (contactMap.keys.contains(initial)) {
          model = contactMap[initial]!;
        }
        else {
          model = ContactModel(section: initial, contacts: []);
          contactMap[initial] = model;
          contactList.add(model);
        }

        for (var phone in contact.phones) {
          var contactItem = ContactItem(contact.displayName, phone.number.removeAllWhitespace.trim());
          model.getContacts.add(contactItem);

          contactItem.imported = isSynced(contactItem);
          if (contactItem.imported == true) {
            state.checkList.add(contactItem.toMap());
          }

          state.totalCount++;
        }
      }
    } on PlatformException catch (e) {
      logger.d(e);
    } finally {
    }

    contactList.sort((a, b) => a.compareTo(b));

    cancelLoading();
    state.contactList.addAll(contactList);
    update(["list_view", "total_item"]);
  }

  @override
  String getRemotePath() {
    return UTEPedConst.pathContact;
  }

  @override
  String getStoragePath() {
    return UTEPedConst.pathDevice;
  }

  @override
  void initState() {
    state.saveList = read(contactsSynced, defaultValue: []);
  }

  @override
  Future<void> onReady() async {
    var hasPermission = await Permission.contacts.isGranted;
    if (!hasPermission) {
      Permission.contacts.request().then((value) => {
        if (value.isGranted) {
          _fetchContacts()
        }
        else {
          showPermissionDialog(LocaleKeys.contact_permission_tips.ts)
        }
      });
    }
    else {
      _fetchContacts();
    }
    super.onReady();
  }

  @override
  void onRemoteEvent(event, method) {
    if (methodSyncContactsInfoToDevice == method) {
      var action = event[UTEPedConst.keyAction];
      var value = event[UTEPedConst.keyValue];
      /// int START = 1; int FINISH = 2;int FAIL = 3;
      if (UTEPedConst.actionSyncContactState == action) {
        state.syncState.value = value;
        if (value == UTEPedConst.syncStateFail) {
          Get.back();
        }
        else if (value == UTEPedConst.syncStateFinish) {
          state.isSyncing.value = false;
          logger.d("sync contacts finish");
          save(contactsSynced, state.saveList);
          update(["dialog_item"]);
          delayed(()=>Get.back(), milliseconds: 2000);
        }
      }
      else if (UTEPedConst.actionSyncContactProgress == action) {
        state.syncProgress.value = value;
        logger.d("sync contacts progress $value");
        state.progressNotifier?.value = state.syncProgress.value.toDouble();
        // update(["dialog_item"]);
      }
    }
  }

  bool isSynced(ContactItem contact) {
    if (state.saveList.isNotEmpty) {
      var exist = state.saveList.firstWhereOrNull((element) =>
          element == "${contact.name}-${contact.phone}");
      if (exist != null) {
        return true;
      }
    }

    return false;
  }

  doImportContact() {
    if (state.checkList.isNotEmpty) {
      state.isSyncing.value = true;
      vRemoteReqAsync(methodSyncContactsInfoToDevice, {UTEPedConst.typeList: state.checkList});
    }

    update(["list_view", "bottom_sheet"]);
  }

  onContactCheck(ContactItem contact, bool? value) {
    contact.imported = value;
    if (value == true) {
      state.checkList.add(contact.toMap());
      state.saveList.add("${contact.name}-${contact.phone}");
    }
    else if (state.checkList.contains(contact.toMap())){
      state.checkList.remove(contact.toMap());
      state.saveList.remove("${contact.name}-${contact.phone}");
    }

    update(["list_view","title_item"]);
  }

  onSelectAll(bool? selectAll) {
    state.isSelectAll = selectAll!;
    int count = 0;
    for (var contactModel in state.contactList) {
      for (var contact in contactModel.getContacts) {
        if (selectAll) {
          contact.imported = true;
          state.checkList.add(contact.toMap());
          state.saveList.add("${contact.name}-${contact.phone}");
        }
        else {
          contact.imported = false;
        }
        count++;
        if (selectAll && count >= 100) {
          break;
        }
      }
      if (selectAll && count >= 100) {
        break;
      }
    }

    if (!selectAll) {
      state.checkList.clear();
    }

    update(["list_view", "bottom_sheet"]);
  }
}
